<?php

namespace App\Repositories;

use App\Models\ChannelOrder;
use App\Models\ChannelOrderRead;
use App\Models\WechatUser;
use App\Models\House;
use App\Models\Cooperation;
use App\Models\Item;
use App\Models\ItemOrder;
use App\Models\ChannelUser;
use InfyOm\Generator\Common\BaseRepository as iBaseRepository;
use Illuminate\Support\Facades\DB;

class ChannelOrderRepository extends iBaseRepository
{
    /**
     * @var array
     */
    protected $fieldSearchable = [
        'channel_id',
        'house_id',
        'wechat_user_id',
        'consult_content',
        'status'
    ];

    /**
     * Configure the Model
     **/
    public function model()
    {
        return ChannelOrder::class;
    }

    /**
     * 获取渠道预约列表
     */
    public function getChannelOrders($channelId, $request)
    {
        $this->applyCriteria();
        $this->applyScope();
        $orders = $this->model->select(['id', 'channel_id', 'house_id', 'wechat_user_id', 'consult_content', 'created_at'])
            ->where('channel_id', '=', $channelId)
            ->with('hasWechatUser')
            ->with('hasHouse')
            ->orderBy('channel_orders.id', 'desc')
            ->simplePaginate($request['limit'] ?? 20);

        if ($orders->items())
        {
            foreach ($orders as $key => $val)
            {
                $orders[$key]['wechat_user'] = $val->hasWechatUser;
                unset($orders[$key]->hasWechatUser);

                $orders[$key]['new_flag'] = ChannelOrderRead::where('wechat_user_id', getLoginWxUserId())
                    ->where('channel_order_id', $val['id'])
                    ->first() ? 0 : 1;

                if ($val->hasHouse)
                {
                    $val->hasHouse->cover = fileUrl($val->hasHouse->cover);
                }
                $orders[$key]['house'] = $val->hasHouse;
                unset($orders[$key]->hasHouse);
            }
        }

        return $orders;
    }

    /**
     * 渠道所有用户预约
     */
    public function getUserOrders($channelId, $request)
    {
        $limit = $request['limit'] ?? 10;
        $search = false;
        if (isset($request['searchFields']) && $request['searchFields'] == 'country' && isset($request['search']))
        {
            $search = [$request['searchFields'] => $request['search']];
        }
        $orders = $this->model->select(['channel_orders.wechat_user_id'])
            ->addSelect(DB::raw('MAX(channel_orders.id) AS id'))
            ->addSelect(DB::raw('COUNT(channel_orders.id) AS num'))
            ->join('houses', function ($join) use ($search) {
                $join->on('houses.id', '=', 'channel_orders.house_id');
                if ($search)
                {
                    $key = key($search);
                    $join->where("houses.{$key}", $search[$key]);
                }
            })
            ->where('channel_orders.channel_id', '=', $channelId)
            ->groupBy('channel_orders.wechat_user_id')
            ->orderBy('channel_orders.id', 'desc')
            ->simplePaginate($limit);

        $orders->appends($request)->links();
        $orders = $orders->toArray();

        if ($orders['data'])
        {
            $userIds = array_column($orders['data'], 'wechat_user_id');
            $users = WechatUser::whereIn('id', $userIds)->select(['id', 'nickname', 'sex', 'headimgurl'])->get()->toArray();
            $userFun = create_function('$origin,$val', '$origin[$val["id"]] = $val; return $origin;');
            $usersArr = array_reduce($users, $userFun);

            $ids = array_column($orders['data'], 'id');
            $maxId = max(array_column($orders['data'], 'id'));
            $secondOrders = $this->model->select(['channel_orders.wechat_user_id'])
                ->addSelect(DB::raw('MAX(channel_orders.id) AS id'))
                ->join('houses', function ($join) use ($search) {
                    $join->on('houses.id', '=', 'channel_orders.house_id');
                    if ($search)
                    {
                        $key = key($search);
                        $join->where("houses.{$key}", $search[$key]);
                    }
                })
                ->where('channel_orders.channel_id', '=', $channelId)
                ->whereIn('channel_orders.wechat_user_id', $userIds)
                ->whereNotIn('channel_orders.id', $ids)
                ->where('channel_orders.id', '<', $maxId)
                ->groupBy('channel_orders.wechat_user_id')
                ->orderBy('channel_orders.id', 'desc')
                ->limit($limit)
                ->get()
                ->toArray();

            if ($secondOrders)
            {
                $secondIds = array_column($secondOrders, 'id');
                $ids = array_merge($ids, $secondIds);
            }

            $houses = $this->model->select(['channel_orders.id', 'channel_orders.house_id', 'channel_orders.wechat_user_id', 'channel_orders.consult_content', 'channel_orders.created_at',
                    'houses.title', 'houses.cover', 'houses.price',
                    'houses.country', 'houses.state_id', 'houses.state', 'houses.state_name', 'houses.county_id', 'houses.county', 'houses.county_name', 'houses.zip_id', 'houses.zip_code', 'houses.zip', 'houses.zip_name'])
                ->join('houses', 'houses.id', '=', 'channel_orders.house_id')
                ->whereIn('channel_orders.id', $ids)
                ->orderBy('channel_orders.id', 'desc')
                ->get()
                ->toArray();

            if ($houses)
            {
                foreach ($houses as $key => $val)
                {
                    $houses[$key]['cover'] = fileUrl($val['cover']);
                    $houses[$key]['new_flag'] = ChannelOrderRead::where('wechat_user_id', getLoginWxUserId())
                        ->where('channel_order_id', $val['id'])
                        ->first() ? 0 : 1;
                }

                $houseFun = create_function('$origin,$val', '$origin[$val["wechat_user_id"]][] = $val; return $origin;');
                $housesArr = array_reduce($houses, $houseFun);
            }

            foreach ($orders['data'] as $key => $val)
            {
                $orders['data'][$key]['new_flag'] = ChannelOrderRead::where('wechat_user_id', getLoginWxUserId())
                    ->where('channel_order_id', $val['id'])
                    ->first() ? 0 : 1;

                $orders['data'][$key]['wechat_user'] = $usersArr[$val['wechat_user_id']] ?? new \stdClass();
                $orders['data'][$key]['houses'] = $housesArr[$val['wechat_user_id']] ?? [];
                $orders['data'][$key]['country_orders'] = $this->model->select(['houses.country'])
                    ->join('houses', 'houses.id', '=', 'channel_orders.house_id')
                    ->where('channel_orders.wechat_user_id', $val['wechat_user_id'])
                    ->groupBy('houses.country')
                    ->orderBy('channel_orders.id', 'desc')
                    ->limit(5)
                    ->pluck('country')
                    ->toArray();

                $orders['data'][$key]['no_cooperation_countries'] = [];
                foreach ($orders['data'][$key]['country_orders'] as $k => $v)
                {
                    $cooperation = Cooperation::select(['id'])
                        ->where('channel_id', $channelId)
                        ->where('status', '<>', Cooperation::STATUS_DEFAULT)
                        ->whereIn('item_id', function ($query) use ($v) {
                            $item = new Item();
                            $query->select('id')
                                ->from($item->table)
                                ->where('country', $v)
                                ->get();
                        })
                        ->limit(1)
                        ->first();

                    if ( ! $cooperation)
                    {
                        $orders['data'][$key]['no_cooperation_countries'][] = $v;
                    }
                }
            }
        }

        return $orders;
    }

    /**
     * 新增预约
     */
    public function addChannelOrder($attributes)
    {
        DB::beginTransaction();
        $channelOrder = parent::create($attributes);
        if ($channelOrder)
        {
            $items = [];
            // 预约专家分享页面
            if ( ! empty($attributes['is_experts_share']))
            {
                // 专家有对应项目方
                if ( ! empty($attributes['item_id']))
                {
                    $cooperation = Cooperation::where('channel_id', $channelOrder->channel_id)
                        ->where('item_id', $attributes['item_id'])
                        ->where('status', '<>', Cooperation::STATUS_DEFAULT)
                        ->first();
                    // 专家对应项目方不是该渠道的合作项目方
                    if ( ! $cooperation)
                    {
                        $items = Item::select(['id'])
                            ->where('country', $attributes['country'] ?? -1)
                            ->whereIn('id', function ($query) use ($channelOrder) {
                                $cooperation = new Cooperation();
                                $query->select('item_id')
                                    ->from($cooperation->table)
                                    ->where('channel_id', $channelOrder->channel_id)
                                    ->where('status', '<>', Cooperation::STATUS_DEFAULT)
                                    ->get();
                            })
                            ->get()
                            ->toArray();
                    }

                    $items[] = ['id' => $attributes['item_id']];
                }
                else // 专家无对应项目方
                {
                    $items = Item::select(['id'])
                        ->where('country', $attributes['country'] ?? -1)
                        ->whereIn('id', function ($query) use ($channelOrder) {
                            $cooperation = new Cooperation();
                            $query->select('item_id')
                                ->from($cooperation->table)
                                ->where('channel_id', $channelOrder->channel_id)
                                ->where('status', '<>', Cooperation::STATUS_DEFAULT)
                                ->get();
                        })
                        ->get()
                        ->toArray();
                }
            }
            elseif ( ! empty($attributes['is_consult_strategy'])) // 预约咨询、攻略
            {
                $items = Item::select(['id'])
                    ->where('country', $attributes['country'] ?? -1)
                    ->whereIn('id', function ($query) use ($channelOrder) {
                        $cooperation = new Cooperation();
                        $query->select('item_id')
                            ->from($cooperation->table)
                            ->where('channel_id', $channelOrder->channel_id)
                            ->where('status', '<>', Cooperation::STATUS_DEFAULT)
                            ->get();
                    })
                    ->get()
                    ->toArray();
            }
            elseif ($channelOrder->house_id > 0) // 预约房源
            {
                $house = House::find($channelOrder->house_id);
                if ($house)
                {
                    // 房源有指定项目方
                    if ($house->item_id)
                    {
                        $items[] = ['id' => $house->item_id];
                    }
                    else // 房源无指定项目方
                    {
                        $items = Item::select(['id'])
                            ->where(function ($query) use ($house) {
                                if ($house->country == 0) // 美国
                                {
                                    $query->where('country', $house->country)
                                        ->where('state_id', $house->state_id);
                                }
                                else
                                {
                                    $query->where('country', $house->country);
                                }
                            })
                            ->whereIn('id', function ($query) use ($channelOrder) {
                                $cooperation = new Cooperation();
                                $query->select('item_id')
                                    ->from($cooperation->table)
                                    ->where('channel_id', $channelOrder->channel_id)
                                    ->where('status', '<>', Cooperation::STATUS_DEFAULT)
                                    ->get();
                            })
                            ->get()
                            ->toArray();
                    }
                }
            }

            if ($items)
            {
                $itemOrders = [];
                foreach ($items as $key => $val)
                {
                    $itemOrders[] = [
                        'item_id' => $val['id'],
                        'channel_id' => $channelOrder->channel_id,
                        'channel_order_id' => $channelOrder->id,
                        'house_id' => $channelOrder->house_id,
                        'wechat_user_id' => $channelOrder->wechat_user_id,
                        'consult_content' => $channelOrder->consult_content,
                        'created_at' => now(),
                        'updated_at' => now()
                    ];
                }
                ItemOrder::insert($itemOrders);
            }
            DB::commit();
        }
        else
        {
            DB::rollBack();
        }

        return $channelOrder;
    }

    /**
     * 渠道所有用户
     */
    public function getChannelUsers($channelId, $request)
    {
        $limit = $request['limit'] ?? 10;
        $users = $this->model->select(['wechat_user_id'])
            ->addSelect(DB::raw('MAX(id) AS id'))
            ->addSelect(DB::raw('COUNT(id) AS num'))
            ->where('channel_id', '=', $channelId)
            ->groupBy('wechat_user_id')
            ->orderBy('id', 'desc')
            ->simplePaginate($limit);

        $usersNum = $users->pluck('num', 'wechat_user_id');
        $users = $users->toArray();

        if ($users['data'])
        {
            $orders = $this->model->select(['id', 'channel_id', 'house_id', 'wechat_user_id', 'consult_content', 'created_at'])
                ->whereIn('id', array_column($users['data'], 'id'))
                ->with('hasWechatUser')
                ->with('hasHouse')
                ->orderBy('id', 'desc')
                ->get();

            if ($orders)
            {
                foreach ($orders as $key => $val)
                {
                    $orders[$key]->wechat_user = $val->hasWechatUser;
                    unset($orders[$key]->hasWechatUser);

                    $val->hasHouse->cover = fileUrl($val->hasHouse->cover);
                    $orders[$key]->house = $val->hasHouse;
                    unset($orders[$key]->hasHouse);
                }
            }
            $users['data'] = $orders->toArray();
        }

        return $users;
    }

    /**
     * 获取客户预约详情
     */
    public function getUserOrderForChannel($id, $channelId, $request)
    {
        $order = $this->model->select(['id', 'channel_id', 'house_id', 'wechat_user_id', 'consult_content', 'created_at'])
            ->where('id', $id)
            ->with('hasWechatUser')
            ->first();

        if ($order)
        {
            $order['wechat_user'] = $order->hasWechatUser;
            unset($order->hasWechatUser);

            $order->user_status = ChannelUser::where('channel_id', $channelId)->where('wechat_user_id', $order->wechat_user_id)->first();

            $order->consult_list = $this->model->select(['houses.country'])
                ->addSelect(DB::raw('COUNT(channel_orders.id) AS num'))
                ->join('houses', 'houses.id', '=', 'channel_orders.house_id')
                ->where('channel_orders.channel_id', $channelId)
                ->where('channel_orders.wechat_user_id', $order->wechat_user_id)
                ->groupBy('houses.country')
                ->get();

            if ($order->consult_list)
            {
                $consultList = $order->consult_list->toArray();
                foreach ($consultList as $key => $val)
                {
                    $order->consult_list[$key]->is_open = Cooperation::where('channel_id', $channelId)
                        ->where('status', Cooperation::STATUS_OPEN)
                        ->whereIn('item_id', function ($query) use ($val) {
                            $item = new Item();
                            $query->select('id')
                                ->from($item->table)
                                ->where('country', $val['country'])
                                ->get();
                        })
                        ->first() ? 1 : 0;
                }
            }

            $orders = $this->model->select(['id', 'channel_id', 'house_id', 'wechat_user_id', 'consult_content', 'created_at'])
                ->where('channel_id', $order->channel_id)
                ->where('wechat_user_id', $order->wechat_user_id)
                ->with('hasHouse')
                ->orderBy('id', 'desc')
                ->simplePaginate($request['limit'] ?? 20);

            if ($orders->items())
            {
                foreach ($orders as $key => $val)
                {
                    if ($val->hasHouse)
                    {
                        $orders[$key]->hasHouse->new_flag = ChannelOrderRead::where('wechat_user_id', getLoginWxUserId())
                            ->where('channel_order_id', $val->id)
                            ->first() ? 0 : 1;
                        $orders[$key]->hasHouse->cover = fileUrl($val->hasHouse->cover);
                        $orders[$key]['house'] = $orders[$key]->hasHouse;
                        unset($orders[$key]->hasHouse);
                    }
                }
            }

            $order['orders'] = $orders;
        }

        return $order;
    }

    /**
     * 添加已读记录
     */
    public function createRead($id, $channelId)
    {
        if (getLoginWxUserId())
        {
            $read = new ChannelOrderRead();
            $attributes = [
                'channel_id' => $channelId,
                'channel_order_id' => $id,
                'wechat_user_id' => getLoginWxUserId()
            ];
            $read->firstOrCreate($attributes);
        }

        return TRUE;
    }

    /**
     * 重置未读
     */
    public function resetUnread($channelId)
    {
        if (getLoginWxUserId())
        {
            $newOrders = $this->model->select(['id'])
                ->where('channel_id', $channelId)
                ->whereNotIn('id', function ($query) use ($channelId) {
                    $read = new ChannelOrderRead();
                    $query->select('channel_order_id')
                        ->from($read->table)
                        ->where('channel_id', $channelId)
                        ->where('wechat_user_id', getLoginWxUserId())
                        ->get();
                })
                ->orderBy('id', 'asc')
                ->get();

            if ($newOrders)
            {
                foreach ($newOrders as $key => $val)
                {
                    $read = new ChannelOrderRead();
                    $attributes = [
                        'channel_id' => $channelId,
                        'channel_order_id' => $val->id,
                        'wechat_user_id' => getLoginWxUserId()
                    ];
                    $read->firstOrCreate($attributes);
                }
            }
        }

        return TRUE;
    }

    /**
     * 推送用户的所有预约信息给项目方
     */
    public function pushUserToItem($channelId, $itemId, $wechatUserId)
    {
        $orders = $this->model->select(['id', 'house_id', 'consult_content'])
            ->where('channel_id', '=', $channelId)
            ->where('wechat_user_id', '=', $wechatUserId)
            ->orderBy('id', 'asc')
            ->get();

        if ($orders)
        {
            $itemOrders = [];
            foreach ($orders as $key => $val)
            {
                $itemOrders[] = [
                    'item_id' => $itemId,
                    'channel_id' => $channelId,
                    'channel_order_id' => $val->id,
                    'house_id' => $val->house_id,
                    'wechat_user_id' => $wechatUserId,
                    'consult_content' => $val->consult_content,
                    'created_at' => now(),
                    'updated_at' => now()
                ];
            }
            ItemOrder::insert($itemOrders);
        }

        return TRUE;
    }
}
